﻿using System;
using System.Net.Sockets;
using System.IO;


namespace Server
{
    public class SocketClient
    {
        const int BufferSize = 8192;//定义buffer缓冲区长度
        byte[] buffer = new byte[BufferSize];

        TcpClient client;
        NetworkStream stream;
        MemoryStream mem;//缓存流
        BinaryReader reader;//缓存流的读取器
        
        public SocketClient(TcpClient _client)
        {
            client = _client;
            LogManager.Log("客户端连接：" + client.Client.RemoteEndPoint);
            stream = client.GetStream();//获取网络流
            mem = new MemoryStream();
            reader = new BinaryReader(mem);

            //开启异步读取数据
            stream.BeginRead(buffer, 0, BufferSize, Read, null);
        }

        //子线程读取消息
        void Read(IAsyncResult ar)
        {
            try
            {
                int readCount = stream.EndRead(ar);
                if (readCount == 0) throw new Exception("读取异常");

                //接收一次，把消息抛给逻辑层
                OnReceive(buffer, readCount);

                lock (client)
                {
                    Array.Clear(buffer, 0, BufferSize);
                    stream.BeginRead(buffer, 0, BufferSize, Read, null);
                }
            }
            catch (Exception e)
            {
                LogManager.Log(e.ToString());
                OnDisconnect();
            }
        }

        //逻辑层，解包，处理[长度+消息]
        void OnReceive(byte[] bytes,int count)
        {
            mem.Seek(0, SeekOrigin.End);//指针指到最后，
            mem.Write(bytes, 0, count);//消息往后追加
            mem.Seek(0, SeekOrigin.Begin);//指针指到开头，开始读消息

            while (RemaindLength() > 4)//判断剩余长度是否够一个int32的长度
            {
                //获取消息长度,指针后移了4位
                int length = reader.ReadInt32();

                if (RemaindLength() >= length)//剩余字节数是否大于消息长度
                {
                    byte[] content = reader.ReadBytes(length);
                    OnMessage(content);
                }
                else
                {
                    mem.Seek(-4,SeekOrigin.Current);//把指针前移4位，保证消息的完整性是[长度+消息]
                    break;
                }
            }

            byte[] remain = reader.ReadBytes(RemaindLength());//把剩余的半包读取出来
            mem.SetLength(0);//把缓存流清空，
            mem.Write(remain, 0, remain.Length);//写入剩余的半包
        }

        //接到一条消息
        void OnMessage(byte[] content)
        {
            ExecutorPool.Instance.Execute(() =>
            {
                GameServer.OnEvent(this, new ByteBuffer(content));
            });
        }

        //获取剩余字节长度
        int RemaindLength()
        {
            return (int)(mem.Length - mem.Position);
        }

        //客户端断开链接
        void OnDisconnect()
        {
            GameServer.Instance.DisConnect(this);
            stream.Close();//流关闭
            client.Close();//客户端关闭
        }

        //往流里面写入==给服务器发消息
        void Write(byte[] content)
        {
            ByteBuffer buf = new ByteBuffer();
            buf.WriteInt(content.Length);
            buf.WriteBytes(content);

            byte[] bytes = buf.ToBytes();
            stream.Write(bytes, 0, bytes.Length);
        }

        //向服务器发送消息
        public void Send(Protocal type, string msg)
        {
            ByteBuffer buf = new ByteBuffer();
            buf.WriteByte((byte)type);
            buf.WriteString(msg);

            Write(buf.ToBytes());
        }
        public void Send(Protocal type, byte[] content)
        {
            ByteBuffer buf = new ByteBuffer();
            buf.WriteByte((byte)type);
            buf.WriteBytes(content);

            LogManager.Log("---------------");
            Write(buf.ToBytes());
        }
    }
}
